#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "semblib.h"  // 假设该头文件包含信号量操作声明
#include <string.h>
#include <unistd.h>  // 补充 fork、waitpid 等函数头文件
#include <stdlib.h>  // 补充标准库函数头文件
#include <sys/wait.h>
#define BUFFER_SIZE 2048

int main() {
    pid_t pid;
    int sem_id;          // 信号量 ID
    int shmid;           // 共享内存段 ID
    char *shm_addr = NULL; // 共享内存首地址
    char buff[40];       // 字符串
    int i = 0;

    // 创建信号量
    sem_id = semget(ftok(".", 'a'), 1, 0666 | IPC_CREAT);
    init_sem(sem_id, 0); // 信号量初始化

    // 创建共享内存
    if ((shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0) {
        perror("shmget");
        return -1;
    }

    pid = fork();
    if (pid == -1) {
        perror("fork");
        return -1;
    } else if (pid == 0) { // 子进程
        // 映射共享内存
        if ((shm_addr = shmat(shmid, 0, 0)) == (char *)-1) {
            perror("shmat");
            return -1;
        }

        while (i < 3) {
            printf("Child process is waiting for data:\n");
            sem_p(sem_id); // P 操作，等待父进程写入
            strcpy(buff, shm_addr); // 读取数据
            printf("Child get data from shared-memory:%s\n", buff);
            sem_v(sem_id); // V 操作，释放信号量
            i++;
        }

        // 分离共享内存（子进程不负责删除共享内存）
        if (shmdt(shm_addr) < 0) {
            perror("shmdt");
            return -1;
        }
    } else { // 父进程
        // 映射共享内存
        if ((shm_addr = shmat(shmid, 0, 0)) == (char *)-1) {
            perror("Parent shmat failed");
            return -1;
        }

        while (i < 3) {
            printf("Please input some string:\n");
            fgets(buff, sizeof(buff), stdin);
            strncpy(shm_addr, buff, strlen(buff));
            sem_v(sem_id); // V 操作，通知子进程读取
            sem_p(sem_id); // P 操作，等待子进程处理完成
            i++;
        }

        // 分离共享内存
        if (shmdt(shm_addr) < 0) {
            perror("Parent:shmdt");
            exit(1);
        }

        // 等待子进程结束，删除共享内存和信号量
        waitpid(pid, NULL, 0);
        shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
        del_sem(sem_id); // 删除信号量
    }
    return 0;
}
